import numpy as np
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import make_regression

# 读取文本文件
try:
    with open('12345.csv', 'r', encoding='utf-8') as f:
        lines = f.readlines()
except FileNotFoundError:
    print("文件未找到，请检查文件名和路径。")
    raise

# 提取表头
header = lines[0].strip().split(',')
data = []
for line in lines[1:]:
    values = line.strip().split(',')
    data.append(values)

plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置中文字体为黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# 重新读取CSV文件进行可视化操作（也可以直接使用上面的df进行操作，这里为了演示完整流程）
new_df = pd.read_csv('12345.csv')

print(f"具体数据如下")
for i in data:
    print(i)

data = pd.read_csv('12345.csv')

# 生成示例数据集（单特征）
X, y = make_regression(n_samples=100, n_features=1, n_informative=1, noise=0.1, random_state=42)

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建随机森林回归模型
model = RandomForestRegressor(n_estimators=100, random_state=42)

# 训练模型
model.fit(X_train, y_train)

# 进行预测
y_pred = model.predict(X_test)

# 评估模型
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)

print(f"均方误差 (MSE): {mse}")
print(f"决定系数 (R²): {r2}")

# 绘制散点图和拟合曲线
plt.scatter(X_test, y_test, color='blue', label='实际值')
plt.scatter(X_test, y_pred, color='red', label='预测值')
plt.plot(X_test, np.sort(y_pred), color='green', label='拟合曲线')
plt.xlabel('特征')
plt.ylabel('目标值')
plt.title('随机森林回归模型预测结果')
plt.legend()
plt.show()
# 读取数据
data1 = pd.read_csv('12345.csv')
# 数据预处理
# 将日期时间列转换为datetime类型
data['日期时间'] = pd.to_datetime(data['日期时间'])
# 提取日期时间的小时和星期几信息
data['hour'] = data['日期时间'].dt.hour
data['weekday'] = data['日期时间'].dt.weekday

# 选择用于预测的特征，这里选择交通情况、天气情况、是否为节假日、小时和星期几等
features = ['交通情况', '天气情况', '是否为节假日', 'hour', 'weekday']
# 对分类特征进行独热编码
X = pd.get_dummies(data[features])
y = data['pm2.5']

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建并训练随机森林回归模型
model = RandomForestRegressor(n_estimators=100, random_state=42)
model.fit(X_train, y_train)

# 定义政策模拟函数
def policy_simulation(X, traffic_factor=0.5):
    """
    模拟推广清洁能源政策对交通排放的影响，进而影响pm2.5
    假设政策使交通排放相关的影响降低50%（通过调整交通情况特征来模拟）
    :param X: 原始特征数据 (DataFrame)
    :param traffic_factor: 交通情况影响因子，默认使影响降低50%
    :return: 调整后的特征数据 (DataFrame)
    """
    traffic_columns = [col for col in X.columns if '交通情况' in col]
    for col in traffic_columns:
        X[col] = X[col] * traffic_factor
    return X

# 模拟政策实施
policy_X_test = policy_simulation(X_test.copy())
policy_y_pred = model.predict(policy_X_test)

# 计算政策实施前后的指标
original_mse = mean_squared_error(y_test, model.predict(X_test))
policy_mse = mean_squared_error(y_test, policy_y_pred)
original_r2 = r2_score(y_test, model.predict(X_test))
policy_r2 = r2_score(y_test, policy_y_pred)

print(f"政策实施前均方误差: {original_mse}")
print(f"政策实施后均方误差: {policy_mse}")
print(f"政策实施前决定系数: {original_r2}")
print(f"政策实施后决定系数: {policy_r2}")

# 绘制政策实施前后pm2.5预测值对比图
plt.scatter(y_test, model.predict(X_test), label='政策实施前预测值', alpha=0.6)
plt.scatter(y_test, policy_y_pred, label='政策实施后预测值', alpha=0.6)
plt.xlabel('真实pm2.5值')
plt.ylabel('预测pm2.5值')
plt.title('推广清洁能源政策对pm2.5的影响')
plt.legend()
plt.show()
# 可视化部分
# 1. 不同城市的碳排放柱状图
plt.figure(figsize=(10, 6))
city_carbon = new_df.groupby('城市')['碳排放'].mean()
city_carbon.plot(kind='bar')
plt.xlabel('城市')
plt.ylabel('平均碳排放')
plt.title('不同城市的平均碳排放对比')
plt.show()

# 2. 随着时间变化的pm2.5折线图
plt.figure(figsize=(12, 6))
new_df.set_index('日期时间')['pm2.5'].plot()
plt.ylabel('PM2.5浓度')
plt.title('PM2.5浓度随时间的变化')
plt.show()

# 3. 不同天气情况下的碳排放箱线图
plt.figure(figsize=(10, 6))
sns.boxplot(x='天气情况', y='碳排放', data=new_df)
plt.xlabel('天气情况')
plt.ylabel('碳排放')
plt.title("不同天气情况下的碳排放分布")
plt.show()

# 4. 是否为节假日与碳排放的关系柱状图
plt.figure(figsize=(8, 6))
holiday_carbon = new_df.groupby('是否为节假日')['碳排放'].mean()
holiday_carbon.plot(kind='bar')
plt.xlabel('是否为节假日')
plt.ylabel('平均碳排放')
plt.title('节假日与非节假日的平均碳排放对比')
plt.show()

# 再次读取data.csv文件。
# 检查缺失值
print(data.isnull().sum())

# 处理缺失值，这里简单使用均值填充数值型数据（如pm2.5、交通情况等可能的数值列），众数填充分类数据（如天气情况等）
# 可根据具体情况进行更细致的处理
num_cols = data.select_dtypes(include=[np.number]).columns
data[num_cols] = data[num_cols].fillna(data[num_cols].mean())

cat_cols = data.select_dtypes(include=['object']).columns
data[cat_cols] = data[cat_cols].fillna(data[cat_cols].mode().iloc[0])

# 将日期时间列转换为datetime类型
data['date_time'] = pd.to_datetime(data['date_time'])

# 提取日期时间的特征，如小时、星期几等
data['hour'] = data['date_time'].dt.hour
data['weekday'] = data['date_time'].dt.weekday

# 选择用于预测的特征，这里包含了提取的时间特征以及原始的pm2.5、交通情况、天气情况、是否为节假日等
features = ['pm2.5', 'traffic_condition', 'weather_condition', 'is_holiday', 'hour', 'weekday']
X = data[features]

# 对分类特征进行编码，这里简单使用独热编码示例，可根据情况调整
X = pd.get_dummies(X, columns=['weather_condition', 'traffic_condition'])

y = data['carbon_emission']

# 使用train_test_split()函数将数据集X和y划分为训练集和测试集，测试集占比为 20%，random_state=42用于保证结果的可重复性。
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建一个RandomForestRegressor模型，设置n_estimators=100表示使用 100 棵决策树，random_state=42用于保证结果的可重复性。
# 使用fit()方法对模型进行训练，传入训练集X_train和y_train。
# 使用predict()方法对测试集X_test进行预测，得到预测结果y_pred。
model = RandomForestRegressor(n_estimators=100, random_state=42)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)

# 计算均方误差
mse = mean_squared_error(y_test, y_pred)
# 计算决定系数
r2 = r2_score(y_test, y_pred)

print(f"Mean Squared Error: {mse}")
print(f"R - squared: {r2}")

# 绘制散点图，展示预测值和真实值之间的关系。
# plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--')：绘制一条红色虚线，表示预测值和真实值相等的情况。
plt.scatter(y_test, y_pred)
plt.xlabel('True Carbon Emission')
plt.ylabel('Predicted Carbon Emission')
plt.title('Carbon Emission Prediction vs True Values')
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'r--')
plt.show()

# model.feature_importances_：获取模型中每个特征的重要性得分。
# np.argsort(feature_importances)[::-1]：对特征重要性得分进行降序排序，得到排序后的索引。
# 使用seaborn库的barplot()函数绘制特征重要性柱状图
feature_importances = model.feature_importances_
features = X.columns
indices = np.argsort(feature_importances)[::-1]

plt.figure(figsize=(10, 6))
plt.title("Feature Importances")
sns.barplot(x=feature_importances[indices], y=features[indices])
plt.show()

# data['city'].unique()：获取city列中的唯一值，即所有城市名称。
# 遍历每个城市，筛选出该城市的数据，绘制pm2.5和carbon_emission之间的散点图。
# plt.legend()：显示图例
cities = data['city'].unique()
plt.figure(figsize=(12, 8))
for city in cities:
    city_data = data[data['city'] == city]
    plt.scatter(city_data['pm2.5'], city_data['carbon_emission'], label=city, alpha=0.6)
plt.xlabel('PM2.5 Concentration')
plt.ylabel('Carbon Emission')
plt.title('Relationship between PM2.5 and Carbon Emission in Different Cities')
plt.legend()
plt.show()

# 再次绘制不同天气情况下碳排放的箱线图。
plt.figure(figsize=(10, 6))
sns.boxplot(x='weather_condition', y='carbon_emission', data=data)
plt.xlabel('Weather Condition')
plt.ylabel('Carbon Emission')
plt.title('Carbon Emission Distribution under Different Weather Conditions')
plt.show()

